grammar Java;

@header {
import java.util.*;
import me.caosh.jparser.model.*;
}

@members {
    private String packageDef;
    private List<String> imports = new ArrayList<>();
    private Interface intface = new Interface();
    private List<Method> methods = new ArrayList<>();

    public Interface getInterface() { return intface; }
    public List<Method> getMethods() { return methods; }
    public void setPackageDef(String  packageDef) { this.packageDef = packageDef; }
    public String getPackageDef() { return packageDef; }
    public void addImport(String  imp) { this.imports.add(imp); }
    public List<String> getImports() { return imports; }
}

// java interface parser
java : packag imports clazz;

packageName : ID (DOT ID)* (DOT STAR)?;
packag : PACKAGE pkg=packageName SEMI { setPackageDef($pkg.text); };
imports : imprt*;
imprt : IMPORT pkg=packageName SEMI { addImport($pkg.text); };

clazz : document? annotation? MODIFIER? INTERFACE
    nam=ID { getInterface().setName($nam.text); }
    BRACE_BEGIN member* BRACE_END;

annotation : AT ID (PAR_BEGIN (annotationParam (COMMA annotationParam)*)? PAR_END)?;
annotationParam : ID ASSIGN CONST;

member : field | method;
field :  document? type ID (ASSIGN CONST)? SEMI;
method locals [ Method mtd = new Method(); ]
    : methodDocument? annotation? MODIFIER? ret=type { $method::mtd.setReturns($ret.text); }
    nam=ID { $method::mtd.setName($nam.text); }
    PAR_BEGIN (parameter (COMMA parameter)*)? PAR_END (THROWS ID)? SEMI
    { methods.add($method::mtd); }
    ;

type : ID (LT type GT)?;
parameter : annotation? typ=type nam=ID { $method::mtd.addParameter($typ.text, $nam.text); };

document : doc=DOCUMENT;
methodDocument : doc=DOCUMENT { $method::mtd.setDocument($doc.text); }
;

THROWS : 'throws';
CLASS : 'class';
INTERFACE : 'interface';
MODIFIER : 'public' | 'protected' | 'private';
PACKAGE : 'package';
IMPORT : 'import';
DOC_BEGIN : '/**';
DOC_END : '*/';
DOCUMENT : DOC_BEGIN .*? DOC_END;
STAR : '*';
DOT : '.';
SEMI: ';';
AT : '@';
PAR_BEGIN : '(';
PAR_END : ')';
ASSIGN : '=';
COMMA : ',';
BRACE_BEGIN : '{';
BRACE_END : '}';
LT : '<';
GT : '>';
CONST : INT | STRING | TRUE | FALSE;
TRUE : 'true';
FALSE : 'false';
STRING : '"' .*? '"';
ID : [_A-Za-z]+[A-Za-z0-9]*;
INT : [1-9][0-9]*;
NEWLINE : '\r' ? '\n' -> skip;
WS : [ \t\r\n]+ -> skip;
LINE_COMMENT : '//' .*? (NEWLINE | EOF) -> skip;
COMMENT : '/*' NEWLINE .*? '*/' -> skip;